﻿using System;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Collections;
using System.Collections.ObjectModel;

using LowLevelGraphics;
using LowLevelGraphics.ColorSpaces;

namespace ImageRecognition2.Forms
{
    /// <summary>
    /// This is ued to show/collect color samples
    /// </summary>
    public partial class FormColorSample : Form
    {        
        protected ObservableCollection<Color> m_aColor = new ObservableCollection<Color>();
        
        protected Color m_LastColor = Color.Transparent;

        protected static FormChild.PixelClickedEventHandler pixelClickedEventHandler = null;
        protected static FormChild.ColorChangedEventHandler colorChangedEventHandler = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="FormColorSample"/> class.
        /// </summary>
        public FormColorSample()
        {
            InitializeComponent();

            listViewColorSample.FullRowSelect = true;
            
            listViewColorSample.SelectedIndexChanged += delegate(object sender, EventArgs e)
            {
                if (listViewColorSample.SelectedItems == null) return;
                if (listViewColorSample.SelectedItems.Count == 0) return;

                object listViewColorSampleSelectedItemsTag = listViewColorSample.SelectedItems[0].Tag;
                if (listViewColorSampleSelectedItemsTag != null)
                {
                    UpdateDisplay((Color)listViewColorSampleSelectedItemsTag, false);
                }
            };

            listView1.Sort();

            InitializeListView(Color.Transparent);

            pixelClickedEventHandler = new FormChild.PixelClickedEventHandler(FormChild_PixelClickedEvent);
            colorChangedEventHandler = new FormChild.ColorChangedEventHandler(FormChild_ColorChangedEvent);
            FormChild.ColorChangedEvent += colorChangedEventHandler;
            FormChild.PixelClickedEvent += pixelClickedEventHandler;
        }

        /// <summary>
        /// Handles the PixelClickedEvent event of the FormChild control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ImageRecognition2.Forms.PixelClickedEventArgs"/> instance containing the event data.</param>
        private void FormChild_PixelClickedEvent(object sender, PixelClickedEventArgs e)
        {
            Color color = e.Color;

            if (!m_aColor.Contains(color))
            {
                m_aColor.Add(color);
                ListViewItem item = new ListViewItem(new string[] { color.A.ToString(), color.R.ToString(), color.G.ToString(), color.B.ToString() });
                item.Tag = color;
                listViewColorSample.Items.Add(item);
            }
        }

        /// <summary>
        /// Initializes the list view.
        /// </summary>
        /// <param name="color">The color.</param>
        /// <returns></returns>
        private Color InitializeListView(Color color)
        {
            ListViewItem itemMain = new ListViewItem(new string[] { color.A.ToString(), color.R.ToString(), color.G.ToString(), color.B.ToString() });
            itemMain.Tag = color;
            this.listViewColorSample.Items.Add(itemMain);

            foreach (AbstractColorSpace colorSpace in Definitions.ColorSpaces)
            {
                Debug.WriteLine(colorSpace.Name);
                try
                {
                    AbstractColorSpace abstractColorSpace = CreateNewColorSpaceFromType(colorSpace, Definitions.Red);

                    ListViewItem item = new ListViewItem(new string[] { abstractColorSpace.Name, "", "", "", "", "", "", "", "", "", "", "", "", "" });
                    item.Tag = abstractColorSpace;
                    listView1.Items.Add(item);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
            return color;
        }

        /// <summary>
        /// Handles the ColorChangedEvent event of the FormChild control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ImageRecognition2.Forms.ColorChangedEventArgs"/> instance containing the event data.</param>
        protected void FormChild_ColorChangedEvent(object sender, ColorChangedEventArgs e)
        {
            UpdateDisplay(e.Color);
        }

        /// <summary>
        /// Updates the display.
        /// </summary>
        private void UpdateDisplay(Color _color)
        {
            UpdateDisplay(_color, false);
        }

        /// <summary>
        /// Updates the display.
        /// </summary>
        private void UpdateDisplay(Color color, bool _bClear)
        {
            if (color == m_LastColor) return;
            m_LastColor = color;

            if (_bClear)
            {
                this.listView1.Items.Clear();
                this.listViewColorSample.Items.Clear();
            }

            int nIndex = 0;
            foreach (ListViewItem item in this.listView1.Items)
            {
                AbstractColorSpace abstractColorSpace = (AbstractColorSpace)item.Tag;
                AbstractColorSpace space = CreateNewColorSpaceFromType(abstractColorSpace, color);
                listView1.Items[nIndex].SubItems[1].Text = space.GetValues()[0].ToString();
                listView1.Items[nIndex].SubItems[2].Text = space.GetValues()[1].ToString();
                listView1.Items[nIndex].SubItems[3].Text = space.GetValues()[2].ToString();
                nIndex++;
            }

            double[] aMax = new double[3];
            double[] aMin = new double[3];
            double[] aAverage = new double[3];

            //int nCount = 0;
            //nCount = NewMethod(aMax, aMin, aAverage, nCount);
        }

        /// <summary>
        /// News the method.
        /// </summary>
        /// <param name="aMax">A max.</param>
        /// <param name="aMin">A min.</param>
        /// <param name="aAverage">A average.</param>
        /// <param name="nCount">The n count.</param>
        /// <returns></returns>
        private int NewMethod(double[] aMax, double[] aMin, double[] aAverage, int nCount)
        {
            foreach (AbstractColorSpace colorSpace in Definitions.ColorSpaces)
            {
                foreach (Color colorTemp in m_aColor)
                {
                    AbstractColorSpace abstractColorSpace = CreateNewColorSpaceFromType(colorSpace, colorTemp);
                    object[] dColorSpaceGetValues = abstractColorSpace.GetValues(); ;
                    double[] aValue = new double[]
                    { 
                        Convert.ToDouble(dColorSpaceGetValues[0]),
                        Convert.ToDouble(dColorSpaceGetValues[1]), 
                        Convert.ToDouble(dColorSpaceGetValues[2]) };

                    for (int i = 0; i < 3; i++)
                    {
                        if ((double)aValue[i] > aMax[i])
                        {
                            aMax[i] = aValue[i];
                        }
                        if ((double)aValue[i] < aMin[i])
                        {
                            aMin[i] = aValue[i];
                        }
                    }
                }
                this.listView1.Items[nCount].SubItems[4].Text = aMin[0].ToString();
                this.listView1.Items[nCount].SubItems[5].Text = aMax[0].ToString();
                this.listView1.Items[nCount].SubItems[6].Text = aAverage[0].ToString();

                this.listView1.Items[nCount].SubItems[7].Text = aMin[1].ToString();
                this.listView1.Items[nCount].SubItems[8].Text = aMax[1].ToString();
                this.listView1.Items[nCount].SubItems[9].Text = aAverage[1].ToString();

                this.listView1.Items[nCount].SubItems[10].Text = aMin[2].ToString();
                this.listView1.Items[nCount].SubItems[11].Text = aMax[2].ToString();
                this.listView1.Items[nCount].SubItems[12].Text = aAverage[2].ToString();

                nCount++;
            }
            return nCount;
        }

     
        /// <summary>
        /// Creates the new type of the color space from.
        /// </summary>
        /// <param name="_abstractColorSpace">The _abstract color space.</param>
        /// <param name="_color">The _color.</param>
        /// <returns></returns>
        public AbstractColorSpace CreateNewColorSpaceFromType(AbstractColorSpace _abstractColorSpace, Color _color)
        {
            AbstractColorSpace abstractColorSpace = (AbstractColorSpace)Activator.CreateInstance(_abstractColorSpace.GetType(), new object[] { _color});
            return abstractColorSpace;
        }

        /// <summary>
        /// Handles the Click event of the deleteItemToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void deleteItemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.listViewColorSample.Items.Remove(this.listViewColorSample.SelectedItems[0]);
        }

        /// <summary>
        /// Handles the Click event of the clearListToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void clearListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.m_aColor.Clear();
            this.listViewColorSample.Items.Clear();
        }

        /// <summary>
        /// Handles the Click event of the copyToClipboardToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void copyToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string sText = string.Empty;
            foreach(ListViewItem item in listViewColorSample.Items)
            {
                for (int i = 0; i < item.SubItems.Count; i++)
                {
                    sText += item.SubItems[i].Text + ";";
                }

                sText = sText.TrimEnd(';');

                sText += Environment.NewLine;
            }
            Clipboard.SetData(DataFormats.Text, sText);
        }

        /// <summary>
        /// Handles the Click event of the loadListToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void loadListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            //fd.Filter = 
            if (fd.ShowDialog() != DialogResult.OK) return;

            this.listViewColorSample.Items.Clear();

            int nMinR = 300;
            int nMaxR = 0;

            int nMinG = 300;
            int nMaxG = 0;

            int nMinB = 300;
            int nMaxB = 0;

            string sText = fd.FileName;
            string[] aLine = Regex.Split(sText, Environment.NewLine);

            foreach (string sLine in aLine)
            {
                string sTempLine = sLine;
                string[] aElement = sTempLine.Split(';');

                int nA = Convert.ToInt32(aElement[0]);

                int nR = Convert.ToInt32(aElement[1]);
                if (nR < nMinR) nMinR = nR;
                if (nR > nMaxR) nMaxR = nR;

                int nG = Convert.ToInt32(aElement[2]);
                if (nG < nMinG) nMinG = nG;
                if (nG > nMaxG) nMaxG = nG;

                int nB = Convert.ToInt32(aElement[3]);
                if (nB < nMinB) nMinB = nB;
                if (nB > nMaxB) nMaxB = nB;

                listViewColorSample.Items.Add(new ListViewItem(new string[]{nA.ToString(), nR.ToString(), nG.ToString(), nB.ToString()}));
                m_aColor.Add(Color.FromArgb(nA, nR, nG, nB));
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data.</param>
        protected override void OnClosing(CancelEventArgs e)
        {
            FormChild.PixelClickedEvent -= pixelClickedEventHandler;
            FormChild.ColorChangedEvent -= colorChangedEventHandler;
            base.OnClosing(e);
        }
    }
}
